#include "widget.h"
#include "GL/gl.h"
#include <QImage>

#define BUFFER_OFFSET(offset) ((void*) (offset))

Widget::Widget(QOpenGLWidget *parent)
    :QOpenGLWidget(parent)
{
    setWindowTitle("坐标系统");
    m_angle = 0.0;
    m_timer = new QTimer;
    m_timer->setInterval(30);
    connect(m_timer, SIGNAL(timeout()), this, SLOT(timeout()));
    m_timer->start();
    //    QVector4D vec(1.0f, 0.0f, 0.0f, 1.0f);
    //    QMatrix4x4 trans;
    //    qInfo()<<"vec"<<vec;
    //    qInfo()<<"trans"<<trans;
    //    trans.translate(QVector3D(1.0f, 1.0f, 0.0f));
    //    vec = trans * vec;
    //    qInfo()<<"vec"<<vec;
}

Widget::~Widget()
{

}

void Widget::initializeGL()
{
    initializeOpenGLFunctions();

    glEnable(GL_TEXTURE_2D);
    glEnable(GL_DEPTH_TEST);

    m_program = new QOpenGLShaderProgram(this);

    //编译代码-添加顶点着色器
    m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/triangles.vert");
    //编译代码-添加片段着色器
    m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/triangles.frag");

    //链接着色器
    m_program->link();

    //VAO，VBO数据部分
    float vertices[] = {
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
         0.5f, -0.5f, -0.5f,  1.0f, 0.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,

        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,

        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
         0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  1.0f, 1.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,

        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f
    };


    //得到顶点属性名在着色器参数列表中的位置-0
    m_posAttr = m_program->attributeLocation("aPos");
//    m_colorAttr = m_program->attributeLocation("aColor");
    m_texCoordAttr = m_program->attributeLocation("aTexCoord");

    glGenVertexArrays(1, m_VAO);
    glBindVertexArray(m_VAO[0]);

    glGenBuffers(1, m_VBO);
    glBindBuffer(GL_ARRAY_BUFFER, m_VBO[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    //链接顶点属性
    glVertexAttribPointer(m_posAttr, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), BUFFER_OFFSET(0));
//    glVertexAttribPointer(m_colorAttr, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), BUFFER_OFFSET(3*sizeof(GLfloat)));
    glVertexAttribPointer(m_texCoordAttr, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), BUFFER_OFFSET(3*sizeof(GLfloat)));

    glEnableVertexAttribArray(m_posAttr);
//    glEnableVertexAttribArray(m_colorAttr);
    glEnableVertexAttribArray(m_texCoordAttr);

    m_projection = m_program->uniformLocation("projection");
    m_view = m_program->uniformLocation("view");
    m_model = m_program->uniformLocation("model");

    //索引缓冲对象
//    glGenBuffers(1, m_EBO);
//    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_EBO[0]);
//    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    //解绑缓存着色器（绑定和解绑的顺序很重要，勿更改）
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    //生成纹理
    m_textureBg = new QOpenGLTexture(QImage(":/wall.jpg").mirrored());
    m_textureBg->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
    m_textureBg->setMagnificationFilter(QOpenGLTexture::Linear);
}

void Widget::resizeGL(int w, int h)
{
    glViewport(0, 0, w, h);
}

void Widget::paintGL()
{
    glClearColor(0.2f, 0.3f, 0.3f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    m_program->bind();

    glBindVertexArray(m_VAO[0]);

    m_textureBg->bind();

    QMatrix4x4 projection, view;

    float ratio = (float)width() / (float)height();

    projection.perspective(45.0f, ratio, 0.1f, 100.0f);

    QVector3D camera = QVector3D(0.0f, 0.0f, 3.0f);
    view.lookAt(camera, QVector3D(0.0f, 0.0f, 0.0f), QVector3D(0.0f, 1.0f, 0.0f));

    m_program->setUniformValue(m_projection, projection);
    m_program->setUniformValue(m_view, view);

    //显示10个立方体
    QVector3D cubePositions[] = {
      QVector3D( 0.0f,  0.0f,  0.0f),
      QVector3D( 2.0f,  5.0f, -15.0f),
      QVector3D(-1.5f, -2.2f, -2.5f),
      QVector3D(-3.8f, -2.0f, -12.3f),
      QVector3D( 2.4f, -0.4f, -3.5f),
      QVector3D(-1.7f,  3.0f, -7.5f),
      QVector3D( 1.3f, -2.0f, -2.5f),
      QVector3D( 1.5f,  2.0f, -2.5f),
      QVector3D( 1.5f,  0.2f, -1.5f),
      QVector3D(-1.3f,  1.0f, -1.5f)
    };

    for(unsigned int i = 0; i< 10; i++)
    {
        QMatrix4x4 model;
//        model.scale(QVector3D(0.5, 0.5, 0.5));
        model.translate(cubePositions[i]);
        float angle = 20.0f * i;
        model.rotate(angle+m_angle, QVector3D(0.5f, 1.0f, 0.0f));

        m_program->setUniformValue(m_model, model);

        glDrawArrays(GL_TRIANGLES, 0, 36);
    }


    m_textureBg->release();
    m_program->release();
}

void Widget::timeout()
{
    m_angle+=2.0;
    if(m_angle>360.0) m_angle = 0.0;
    update();
}
